package com.uinnova.product.eam.service.resource.Impl;

import com.binary.core.util.BinaryUtils;
import com.uinnova.product.eam.base.model.FileResourceMeta;
import com.uinnova.product.eam.base.model.ResourceInfo;
import com.uinnova.product.eam.comm.model.es.CEamResource;
import com.uinnova.product.eam.comm.model.es.EamResource;
import com.uinnova.product.eam.model.vo.DefaultFileVo;
import com.uinnova.product.eam.service.IEamArtifactSvc;
import com.uinnova.product.eam.service.es.IamsEamESResourceDao;
import com.uinnova.product.eam.service.resource.IEamResourceSvc;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.permission.business.CurrentUserInfo;
import com.uino.bean.sys.base.Logo;
import com.uino.dao.util.ESUtil;
import com.uino.service.util.FileUtil;
import com.uino.util.rsm.RsmUtils;
import com.uino.util.sys.CommonFileUtil;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class EamResourceSvcImpl implements IEamResourceSvc {

    @Resource
    private IamsEamESResourceDao iamsEamESResourceDao;

    @Value("${http.resource.space}")
    private String urlPath;

    @Value("${local.resource.space}")
    private String localPath;

    @Autowired
    private IUserApiSvc userSvc;

    @Autowired
    private RsmUtils rsmUtils;

    /**
     * 文档合法性正则
     */
    @Value("${uino.eam.word_name_regex}")
    private String resNameRegex;

    @Resource
    private IEamArtifactSvc artifactSvc;

    @PostConstruct
    public void initAddDefaultImage() {
        List<EamResource> list = FileUtil.getData("/initdata/uino_eam_resource.json", EamResource.class);
        iamsEamESResourceDao.saveOrUpdateBatch(list);
    }

    @Override
    public Long saveOrUpdate(EamResource resource) {
        if(BinaryUtils.isEmpty(resource.getId())){
            resource.setId(ESUtil.getUUID());
            resource.setCreateTime(ESUtil.getNumberDateTime());
        }
        resource.setModifyTime(ESUtil.getNumberDateTime());
        return iamsEamESResourceDao.saveOrUpdate(resource);
    }

    @Override
    public List<ResourceInfo> selectListByWords(List<Long> ids, List<String> words){
        BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
        queryBuilder.must(QueryBuilders.termsQuery("id", ids));
        if(!CollectionUtils.isEmpty(words)){
            BoolQueryBuilder queryWords = new BoolQueryBuilder();
            words.forEach(word -> queryWords.should(QueryBuilders.multiMatchQuery(word, new String[]{"name","operator"})
                    .operator(Operator.AND).type(MultiMatchQueryBuilder.Type.PHRASE_PREFIX).lenient(true)));
            queryBuilder.should(queryWords);
        }
        List<EamResource> resources = iamsEamESResourceDao.getListByQuery(queryBuilder);
        List<ResourceInfo> list = resources.stream().map(ResourceInfo::new).collect(Collectors.toList());
        list.forEach(each -> each.setResPath(urlPath + each.getResPath()));
        return list;
    }

    @Override
    public List<EamResource> getByName(String name) {
        CEamResource eamResource = new CEamResource();
        eamResource.setName(name);
        return iamsEamESResourceDao.getSortListByCdt(eamResource, new ArrayList<>());
    }

    @Override
    public List<ResourceInfo> upload(MultipartFile[] files, SysUser sysUser) {
        List<ResourceInfo> resources = new ArrayList<>(files.length);
        CurrentUserInfo userInfo = userSvc.getCurrentUser();
        String userName = userInfo == null ? "" : userInfo.getUserName();
        for (MultipartFile file : files) {
            EamResource resource = saveFile(file, userName);
            if(resource == null){
                continue;
            }
            resources.add(new ResourceInfo(resource));
        }
        return resources;
    }

    @Override
    public List<FileResourceMeta> download(List<Long> resIds) {
        if(CollectionUtils.isEmpty(resIds)){
            return new ArrayList<>();
        }
        BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
        queryBuilder.must(QueryBuilders.termsQuery("id", resIds));
        List<EamResource> resources = iamsEamESResourceDao.getListByQuery(queryBuilder);
        if(CollectionUtils.isEmpty(resources)){
            return new ArrayList<>();
        }
        return resources.stream().map(each -> new FileResourceMeta(each, urlPath)).collect(Collectors.toList());
    }

    @Override
    public List<FileResourceMeta> queryByType(Integer type) {
        BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
        queryBuilder.must(QueryBuilders.termQuery("type", type));
        List<EamResource> resources = iamsEamESResourceDao.getListByQuery(queryBuilder);
        if(CollectionUtils.isEmpty(resources)){
            return new ArrayList<>();
        }
        return resources.stream().map(each -> new FileResourceMeta(each, urlPath)).collect(Collectors.toList());
    }

    @Override
    public List<ResourceInfo> uploadFileByType(MultipartFile[] files, Integer type) {
        List<ResourceInfo> resources = new ArrayList<>(files.length);
        CurrentUserInfo userInfo = userSvc.getCurrentUser();
        String userName = userInfo == null ? "" : userInfo.getUserName();
        for (MultipartFile file : files) {
            EamResource resource = saveFile(file, userName, type);
            if(resource == null){
                continue;
            }
            resources.add(new ResourceInfo(resource));
        }
        return resources;
    }

    @Override
    public Integer deleteResource(Long id) {
        return iamsEamESResourceDao.deleteById(id);
    }

    @Override
    public List<DefaultFileVo> getImages(Integer type) {
        List<DefaultFileVo> result = new ArrayList<>();
        List<FileResourceMeta> uploadFile = this.queryByType(type);
        //查询上传的图片
        List<DefaultFileVo> customList = new ArrayList<>();
        for (FileResourceMeta each : uploadFile) {
            DefaultFileVo vo = new DefaultFileVo();
            vo.setResPath(each.getResPath());
            vo.setFileId(each.getId());
            vo.setCreateTime(each.getCreateTime());
            if (!BinaryUtils.isEmpty(each.getName())) {
                vo.setImageName(each.getName().substring(0, each.getName().indexOf(".")));
            }
            customList.add(vo);
        }
        customList.sort(Comparator.comparing(DefaultFileVo::getCreateTime));
        if(type == 1){
            //1添加制品默认图
            result.addAll(artifactSvc.defaultImage());
        }else{
            //2添加品牌logo默认图
            result.addAll(this.getDefaultLogos());
        }
        result.addAll(customList);
        return result;
    }

    private List<DefaultFileVo> getDefaultLogos(){
        List<Logo> logoList = CommonFileUtil.getData("/initdata/uino_sys_logo.json", Logo.class);
        List<DefaultFileVo> result = new ArrayList<>();
        for (Logo each : logoList) {
            DefaultFileVo vo = new DefaultFileVo();
            vo.setResPath(urlPath + each.getDefaultUrl());
            vo.setFileId(each.getId());
            vo.setImageName(each.getType());
            vo.setDefaultImg(true);
            vo.setCreateTime(each.getCreateTime());
            result.add(vo);
        }
        return result;
    }

    private EamResource saveFile(MultipartFile file, String operator){
        return this.saveFile(file, operator, null);
    }

    /**
     * 上传文件
     * @param file 文件
     * @param operator 操作人
     * @param type 业务类型：制品示例图=1
     * @return 资源信息
     */
    private EamResource saveFile(MultipartFile file, String operator, Integer type){
        long dateTimeFolder = ESUtil.getNumberDate();
        File destFolder = new File(localPath+"/"+dateTimeFolder);
        if(!destFolder.exists()){
            destFolder.mkdirs();
        }
        String docName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf("."));
        String fileType = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        if (!(file.getOriginalFilename().matches(resNameRegex))) {
            throw new RuntimeException(docName + "文件格式不正确");
        }
        String destFileName = ESUtil.getUUID() + "." + fileType;
        File destFile = new File(destFolder, destFileName);
        String resPath = "/" + dateTimeFolder + "/" + destFileName;
        try {

            file.transferTo(new File(destFile.getCanonicalPath()));

            rsmUtils.uploadRsmFromFile(destFile);

            EamResource resource = new EamResource();
            resource.setCreateTime(System.currentTimeMillis());
            resource.setModifyTime(resource.getCreateTime());
            resource.setId(ESUtil.getUUID());
            resource.setName(docName);
            resource.setOperator(operator);
            resource.setResType(fileType);
            resource.setResPath(resPath);
            resource.setType(type);
            iamsEamESResourceDao.saveOrUpdate(resource);
            return resource;
        } catch (IOException e) {
            log.error("保存文件异常", e);
        }
        return null;
    }


}
